#include "config.h"
#include <string.h>
#include "eeprom.h"
#include "Utility.h"
#include <stdio.h>
#include "stm32f4xx_hal.h"
#include "spi_flash.h"
#include "DBG.h"

#define STORE_BASE 0x08020000
#define CONFIG_VER 2

OCXO_INFO g_Ocxo_info;
Controller_Config g_Controller_config;

//#pragma pack(1)

typedef struct
{
	uint16_t crc;
	OCXO_INFO info;
} OCXO_InfoSave_OLD;

typedef struct
{
	uint16_t crc;
	OCXO_INFO info;
} OCXO_InfoSave;

typedef struct
{
	uint16_t crc;
	Controller_Config config;
} Controller_ConfigSave;
//#pragma pack()

void OcxoInfo_Init(void)
{
	memset(&g_Ocxo_info,0,sizeof(OCXO_INFO));
	g_Ocxo_info.lowNoise = 10;
	g_Ocxo_info.dacValue = 410000;
	g_Ocxo_info.ocxo_agetime = 800;
	strcpy(g_Ocxo_info.ocxo_info, "ocxo");
}

void OcxoInfo_SetStep(float step, double center)
{
	g_Ocxo_info.adjValid = 1;
	g_Ocxo_info.adj_step = step;
	g_Ocxo_info.dacValue = center;
	OcxoInfo_Save();
}

void OcxoInfo_Save(void)
{
	OCXO_InfoSave tmp;
	if(ABS(g_Ocxo_info.lowNoise)<0.01f)
	{
		DBGI("error noise value, can't save\n");
	}
	tmp.crc = getCRC16((uint8_t*)&g_Ocxo_info, sizeof(OCXO_INFO));
	tmp.info = g_Ocxo_info;
	HAL_StatusTypeDef error;
	AA24x_WriteBytes(0, (uint8_t*)&tmp, sizeof(OCXO_InfoSave), &error);
}

void CMD_FormatOcxo(void)
{
	DBGI("format ocxo........\n");
	OcxoInfo_Init();
	OcxoInfo_Save();
}

void CMD_PrintOcxo(void)
{
	DBGI("type = %d\n", g_Ocxo_info.ocxo_type);
	DBGI("history = %d\n", g_Ocxo_info.historyCount);
	DBGI("prehistory= %d\n", g_Ocxo_info.preHistoryCount);
	DBGI("adjvalid=%d value=%f\n", g_Ocxo_info.adjValid, g_Ocxo_info.adj_step);
	DBGI("dacvalue = %d\n", g_Ocxo_info.dacValue);
	DBGI("temp = %f\n", g_Ocxo_info.temp);
	DBGI("noise = %f\n", g_Ocxo_info.lowNoise);
	DBGI("time = %d\n", g_Ocxo_info.time);
	DBGI("info = %s\n", g_Ocxo_info.ocxo_info);
	DBGI("ocxo_age = %d\n",g_Ocxo_info.ocxo_agetime);
}

void CMD_PrintConfig(void)
{
	DBGI("ocxoWarm = %d\n", g_Controller_config.ocxoWarm);
	DBGI("gpstype = %d\n", g_Controller_config.gpsType);
	DBGI("dacoffset = %d\n", g_Controller_config.dacOffset);
	DBGI("10minfix = %f\n", g_Controller_config.offsetFix);
	DBGI("qError=%d\n", g_Controller_config.qError);
	DBGI("qLog = %d Value=%d\n", g_Controller_config.qLongFix, g_Controller_config.qLongValue);
	DBGI("type=%d \n", g_Controller_config.type);
	DBGI("fullscal=%d \n",g_Controller_config.fullscal);
	DBGI("adcZero=%d \n", g_Controller_config.adcZero);
	DBGI("tdctime=%d \n", g_Controller_config.tdctime);
}


void OcxoInfo_Load(void)
{
	OCXO_InfoSave tmp;
	OCXO_InfoSave_OLD *tmp2;
	uint8_t *buf = (uint8_t *)&tmp;
	HAL_StatusTypeDef error;
	for(int i=0;i<sizeof(OCXO_InfoSave);i++)
	{
		buf[i] = AA24x_ReadOneByte(i, &error);
	}
	uint16_t crc1 = getCRC16((uint8_t*)&(tmp.info), sizeof(OCXO_INFO));
	DBGI("crc1=%d load=%d\n", crc1, tmp.crc);
	//crc1 = 0;
	if(crc1 != tmp.crc)
	{
		tmp2 = (OCXO_InfoSave_OLD *)&tmp;
		uint16_t crc2 = getCRC16((uint8_t*)&(tmp2->info), sizeof(OCXO_INFO_OLD));
		//tmp2->crc = crc2;
		if(tmp2->crc == crc2)
		{
			DBGI("move old data......\n");
			strcpy(tmp.info.ocxo_info, "ocxo inited");
			tmp.info.ocxo_agetime = 18000;
			memcpy(&g_Ocxo_info, &tmp.info, sizeof(OCXO_INFO));
			OcxoInfo_Save();
		}
		else
		{
			DBGI("ocxo info bad, reinit and save it.\n");
			OcxoInfo_Init();
			OcxoInfo_Save();
		}
	}
	else
	{	
		memcpy(&g_Ocxo_info, &tmp.info, sizeof(OCXO_INFO));
		g_Ocxo_info.historyCount = 0;
		g_Ocxo_info.ocxo_info[15] = 0;
		DBGI("ocxo info load success. %d\n", g_Ocxo_info.dacValue);
	}
}

void Controller_Config_Init(void)
{
	memset(&g_Controller_config, 0xFF, sizeof(Controller_Config));
	g_Controller_config.version = CONFIG_VER;
	g_Controller_config.dacOffset = 0;
	g_Controller_config.gpsType = 0;
	g_Controller_config.order = 0;
	g_Controller_config.ocxoWarm = 500;
	g_Controller_config.qError = 1;
	g_Controller_config.offsetFix = 70;
	g_Controller_config.qLongFix = 1;
	g_Controller_config.qLongValue = 20;
	g_Controller_config.type = 1;
	g_Controller_config.fullscal = 15000;
	g_Controller_config.adcZero = 450;
	g_Controller_config.tdctime = 50000;
}

void Controller_Config_SaveEx(uint8_t earse);

void Controller_Config_Save(void)
{
	uint8_t needEarse = 0;
	g_Controller_config.order++;
	if(g_Controller_config.order == 2048)
	{
		g_Controller_config.order = 0;
		needEarse = 1;
	}
	Controller_Config_SaveEx(needEarse);
}

void Controller_Config_SaveEx(uint8_t earse)
{
	DBGI("save config order = %d size=%d\n", g_Controller_config.order, sizeof(Controller_Config));
	uint32_t addr = STORE_BASE + 64*g_Controller_config.order;
	Controller_ConfigSave tmp;
	tmp.crc = getCRC16((uint8_t *)&g_Controller_config, sizeof(Controller_Config));
	tmp.config = g_Controller_config;
	HAL_FLASH_Unlock();
	if(earse)
	{
		DBGI("erase flash...\r\n");
		
		FLASH_Erase_Sector(FLASH_SECTOR_5,FLASH_VOLTAGE_RANGE_3);
		FLASH_WaitForLastOperation((uint32_t)0xFFFFFF);
		
		DBGI("erase ok...\r\n");
	}
	uint8_t len = sizeof(Controller_ConfigSave)/4+1;
	uint32_t *p = (uint32_t *)&tmp;
	for(int j=0;j<10;j++)
	{
		HAL_StatusTypeDef ret = HAL_ERROR;
		for(int i=0;i<len;i++)
		{
			__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_PGPERR);
			__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_PGSERR);
			ret = HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD,addr+i*4,*(p+i));
			if(ret != 0)
			{
				break;
			}
		}
		if(ret != 0)
		{
			g_Controller_config.order++;
			if(g_Controller_config.order >= 2048)
			{
				g_Controller_config.order = 0;
			}
		}
		else
		{
			DBGI("save flash success.\n");
			break;
		}
	}
	HAL_FLASH_Lock();
}

uint8_t Controller_IsEmpty(uint8_t *buf, int size)
{
	uint8_t ret = 1;
	for(int i=0;i<size;i++)
	{
		if(buf[i] != 0xFF)
		{
			ret = 0;
			break;
		}
	}
	return ret;
}

void Controller_Config_Load(void)
{
	Controller_ConfigSave *tmp;
	Controller_ConfigSave *pretmp;
	for(int i=0;i<2048;i++)
	{
		tmp = (Controller_ConfigSave *)(STORE_BASE + 64 * i);
		if(Controller_IsEmpty((uint8_t *)tmp, sizeof(Controller_ConfigSave)) && i>0)
		{
			g_Controller_config = pretmp->config;
			if(g_Controller_config.version == 1)
			{
				g_Controller_config.version = CONFIG_VER;
				Controller_Config_Save();
				DBGI("old value = %d\n", g_Ocxo_info.dacValue);
				g_Ocxo_info.dacValue = (g_Ocxo_info.dacValue* 0.11920928955078125);//(1000*1000) / (65536*128)) ;
				g_Ocxo_info.adj_step = g_Ocxo_info.adj_step * 0.11920928955078125l;
				DBGI("new value = %d\n", g_Ocxo_info.dacValue);
				OcxoInfo_Save();
			}
			DBGI("load success, order = %d i=%d\n", g_Controller_config.order, i);
			break;
		}
		else
		{
			uint16_t crc = getCRC16((uint8_t *)&tmp->config, sizeof(Controller_Config));
			if(tmp->crc == crc)
			{
				pretmp = tmp;
			}
			else
			{
				if(i == 0)
				{
					DBGI("init config.\n");
					Controller_Config_Init();
					Controller_Config_SaveEx(1);
					SPI_Flash_EraseTotal();
					break;
				}
			}
		}
	}
}



